package org.csu.onlineedubackend.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 短信工具类
 */
@Component
public class SmsUtil {

    // 互亿无线短信接口配置
    private static final String API_ID = "C68629745";
    private static final String API_KEY = "16f38c7b5319dd47fd8f9bd4a26beaa0";
    private static final String SMS_URL = "http://106.ihuyi.com/webservice/sms.php?method=Submit";
    private static final boolean MOCK_MODE = false; // 是否启用模拟模式，避免实际调用短信API

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 生成随机验证码
     * @return 6位数字验证码
     */
    public String generateSmsCode() {
        Random random = new Random();
        StringBuilder codeBuilder = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            codeBuilder.append(random.nextInt(10));
        }
        return codeBuilder.toString();
    }

    /**
     * 发送短信验证码
     * @param phone 手机号
     * @return 返回发送结果
     */
    public boolean sendSmsCode(String phone) {
        try {
            System.out.println("开始发送短信验证码到: " + phone);
            
            // 生成6位随机验证码
            String code = generateSmsCode();
            System.out.println("生成的验证码: " + code);
            
            // 存入Redis，设置5分钟过期
            redisTemplate.opsForValue().set("sms:code:" + phone, code, 5, TimeUnit.MINUTES);
            System.out.println("验证码已存入Redis，键为: sms:code:" + phone);
            
            // 如果启用模拟模式，直接返回成功，不实际发送短信
            if (MOCK_MODE) {
                System.out.println("【模拟发送】已向" + phone + "发送验证码: " + code);
                return true;
            }
            
            // 发送短信内容
            String content = "您的验证码是：" + code + "。请不要把验证码泄露给其他人。";
            System.out.println("短信内容: " + content);

            // 构造请求参数
            String encodedContent = URLEncoder.encode(content, StandardCharsets.UTF_8.name());
            String postData = "account=" + API_ID + 
                       "&password=" + API_KEY + 
                       "&mobile=" + phone + 
                       "&content=" + encodedContent +
                       "&format=json";
            
            System.out.println("发送的请求参数: " + postData);
            
            return sendHttpRequest(postData);
            
        } catch (Exception e) {
            System.out.println("发送短信时发生异常: " + e.getClass().getName() + ": " + e.getMessage());
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 发送HTTP请求
     */
    private boolean sendHttpRequest(String postData) {
        HttpURLConnection conn = null;
        BufferedReader reader = null;
        
        try {
            // 创建连接
            URL url = new URL(SMS_URL);
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
            conn.setRequestProperty("Accept", "application/json");
            conn.setRequestProperty("User-Agent", "Mozilla/5.0");
            conn.setDoOutput(true);
            conn.setConnectTimeout(10000); // 10秒连接超时
            conn.setReadTimeout(10000);    // 10秒读取超时
            
            // 发送请求
            try (OutputStream os = conn.getOutputStream()) {
                os.write(postData.getBytes(StandardCharsets.UTF_8));
                os.flush();
            }
            
            // 获取响应状态
            int responseCode = conn.getResponseCode();
            System.out.println("HTTP响应码: " + responseCode);
            
            // 读取响应
            StringBuilder response = new StringBuilder();
            try {
                reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
            } catch (IOException e) {
                System.out.println("读取响应失败: " + e.getMessage());
                
                // 尝试读取错误流
                if (conn.getErrorStream() != null) {
                    reader = new BufferedReader(new InputStreamReader(conn.getErrorStream(), StandardCharsets.UTF_8));
                    String line;
                    System.out.println("错误响应内容:");
                    while ((line = reader.readLine()) != null) {
                        System.out.println(line);
                    }
                }
                return false;
            }
            
            String responseBody = response.toString();
            System.out.println("API响应内容: " + responseBody);
            
            // 由于我们使用JSON格式，检查code值
            boolean success = responseBody.contains("\"code\":2") || responseBody.contains("\"code\": 2") || 
                            responseBody.contains("\"code\":\"2\"") || responseBody.contains("\"code\": \"2\"");
            
            // 兼容XML格式检查
            if (!success) {
                success = responseBody.contains("<code>2</code>");
            }
            
            System.out.println("短信发送" + (success ? "成功" : "失败"));
            
            // 如果短信发送成功，打印出验证码供测试使用
            if (success) {
                System.out.println("======================================");
                System.out.println("🔐 测试用验证码: " + redisTemplate.opsForValue().get("sms:code:" + getPhoneFromPostData(postData)));
                System.out.println("======================================");
            }
            
            return success;
        } catch (Exception e) {
            System.out.println("HTTP请求过程中出错: " + e.getMessage());
            e.printStackTrace();
            return false;
        } finally {
            // 关闭资源
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    System.out.println("关闭reader失败: " + e.getMessage());
                }
            }
            if (conn != null) {
                conn.disconnect();
            }
        }
    }

    /**
     * 验证短信验证码
     * @param phone 手机号
     * @param code 用户输入的验证码
     * @return 是否验证通过
     */
    public boolean verifySmsCode(String phone, String code) {
        String savedCode = redisTemplate.opsForValue().get("sms:code:" + phone);
        System.out.println("验证码验证 - 手机号: " + phone + ", 用户输入: " + code + ", 存储的验证码: " + savedCode);
        
        if (savedCode != null && savedCode.equals(code)) {
            // 验证成功后删除Redis中的验证码
            redisTemplate.delete("sms:code:" + phone);
            System.out.println("验证码验证通过，已从Redis删除");
            return true;
        }
        
        System.out.println("验证码验证失败");
        return false;
    }

    /**
     * MD5加密
     */
    private String md5(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] messageDigest = md.digest(input.getBytes(StandardCharsets.UTF_8));
            StringBuilder hexString = new StringBuilder();
            for (byte b : messageDigest) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) hexString.append('0');
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            System.out.println("MD5加密失败: " + e.getMessage());
            return null;
        }
    }

    /**
     * 从POST数据中提取手机号
     */
    private String getPhoneFromPostData(String postData) {
        if (postData == null) return "";
        
        String[] params = postData.split("&");
        for (String param : params) {
            if (param.startsWith("mobile=")) {
                return param.substring("mobile=".length());
            }
        }
        return "";
    }
} 